package com.cango.student.methodHandle;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

// invoke方法进行类型匹配的基本规则是对比返回值类型和每个参数的类型是否都可以相互匹配。假设源类型为S，目标类型为T，则基本规则如下：
//        1、可以通过java的类型转换来完成，一般从子类转成父类，比如从String到Object类型；
//        2、可以通过基本类型的转换来完成，只能将类型范围的扩大，比如从int切换到long；
//        3、可以通过基本类型的自动装箱和拆箱机制来完成，例如从int到Integer；
//        4、如果S有返回值类型，而T的返回值类型为void，则S的返回值会被丢弃。
//        5、如果S的返回值是void，而T的返回值是引用类型，T的返回值会是null；
//        6、如果S的返回值是void，而T的返回值是基本类型，T的返回值会是0；
public class MethodHandleTest2 {
    public MethodHandle getHandler() {
        MethodHandle mh = null;
        MethodType mt = MethodType.methodType(void.class);
        MethodHandles.Lookup lk = MethodHandles.lookup();

        try {
            mh = lk.findVirtual(MethodHandleTest.class, "print", mt);
        } catch (Throwable e) {
            e.printStackTrace();
        }

        return mh;
    }

    public void print() {
        System.out.println("print");
    }

    public static void main(String[] args) throws Throwable {
        MethodHandleTest2 mht = new MethodHandleTest2();
        MethodHandle mh = mht.getHandler();
        // 如果S的返回值是void，而T的返回值是引用类型，T的返回值会是null；
        int result1 = (int) mh.invoke(mht);
        // 如果S的返回值是void，而T的返回值是引用类型，T的返回值会是null；
        Object result2 = mh.invoke(mht);

        System.out.println("result 1:" + result1);
        System.out.println("result 2:" + result2);
    }
}

